#include "Shader.h"
Shader::Shader(const char* vertexShaderPath, const char* fragmentShaderPath) {
	this->openShaderFile(vertexShaderPath, fragmentShaderPath);
	this->getShaderSource();
	this->compileShaderSource();
	this->linkShaderProgram();
	this->setProgramUse(program);
}

Shader::~Shader() {
	vertexShaderFile.close();
	fragmentShaderFile.close();
	glUseProgram(0);
}

bool Shader::openShaderFile(const char* vertexShaderPath, const char* fragmentShaderPath) {
	vertexShaderFile.open(vertexShaderPath, ios_base::in);
	fragmentShaderFile.open(fragmentShaderPath, ios_base::in);

	if (!vertexShaderFile.is_open()) {
		strerror_s(errorMsg, 1024, errno);
		cerr << "Open Shader File Error:" << vertexShaderPath << " " << "Cause:" << errorMsg << endl;
		return false;
	}

	if (!fragmentShaderFile.is_open()) {
		strerror_s(errorMsg, 1024, errno);
		cerr << "Open Shader File Error:" << fragmentShaderPath << " " << "Cause:" << errorMsg << endl;
		return false;
	}
	cout << "Open Shader File Success" << endl;
	return true;
}

void Shader::getShaderSource() {
	string line;
	while (getline(vertexShaderFile, line)) {
		vertexShaderSource += line + "\n";
	}

	while (getline(fragmentShaderFile, line)) {
		fragmentShaderSource += line + "\n";
	}
	cout << "Get Shader Source Success" << endl;

}

bool Shader::compileShaderSource() {
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	const char* vertexShaderSource1 = vertexShaderSource.c_str();
	const char* fragmentShaderSource1 = fragmentShaderSource.c_str();

	glShaderSource(vertexShader, 1, &vertexShaderSource1, nullptr);
	glCompileShader(vertexShader);
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(vertexShader, 1024, nullptr, errorMsg);
		cout << "Compile Vertex Shader Error:" << errorMsg << endl;
		return false;
	}

	glShaderSource(fragmentShader, 1, &fragmentShaderSource1, nullptr);
	glCompileShader(fragmentShader);
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragmentShader, 1024, nullptr, errorMsg);
		cout << "Compile Fragment Shader Error:" << errorMsg << endl;
		return false;
	}
	cout << "Compile Shader Program Success" << endl;
	return true;
}

bool Shader::linkShaderProgram() {
	program = glCreateProgram();
	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glLinkProgram(program);
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(program, 1024, nullptr, errorMsg);
		cout << "Link Program Error:" << errorMsg << endl;
		return false;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
	return true;
}